package cn.zwk.common.utils;

import com.alibaba.fastjson2.JSON;
import com.sun.jmx.remote.internal.ArrayQueue;

import java.util.*;

public class TreeUtils {


    public static <T extends Tree> Map<Long, T> buildMapTree(List<T> nodes, T root) {
        Map<Long, T> indexMap = new HashMap<>();
        indexMap.put(root.getTreeId(), root);
        nodes.forEach(node -> indexMap.put(node.getTreeId(), node));
        nodes.forEach(node -> {
            Tree parent = indexMap.get(node.getTreePid());
            if (parent != null) {
                parent.getChildren().add(node);
            }
        });
        return indexMap;
    }

    public static <T extends Tree> List<T> buildTree(List<T> nodes) {
        List<T> children = (List<T>) buildMapTree(nodes, (T) new TreeRoot()).get(0L).getChildren();
        return children;
    }


    public static <T extends Tree & Comparable<T>> List<T> treeSort(List<T> nodes) {
        List<List<T>> cur = new ArrayList<>();
        cur.add(nodes);
        while (!cur.isEmpty()) {
            List<List<T>> child = new ArrayList<>();
            for (List<T> level : cur) {
                level.sort(T::compareTo);
                level.forEach(node -> {
                    List<? extends Tree> children = node.getChildren();
                    child.add((List<T>) children);
                });
            }
            cur = child;
        }
        return nodes;
    }

    public static <T extends Tree & Comparable<T>> List<T> buildSortTree(List<T> nodes) {
        return treeSort(buildTree(nodes));
    }

    public static <T extends Tree & Comparable<T>> List<T> parentPath(List<T> nodes,T root,Long id){
        LinkedList<T> result = (LinkedList<T>) parentPathNoRoot(nodes, root, id);
        result.addFirst(root);
        return result;
    }

    public static <T extends Tree & Comparable<T>> List<T> parentPathNoRoot(List<T> nodes,T root,Long id){
        LinkedList<T> list = new LinkedList<>();
        Map<Long, T> indexMap = buildMapTree(nodes, root);
        T curr = indexMap.get(id);
        while (curr != root) {
            list.addFirst(curr);
            curr = indexMap.get(curr.getTreePid());
        }
        return list;
    }

    private static class TreeRoot extends Tree {
        @Override
        public Long getTreeId() {
            return 0L;
        }

        @Override
        public Long getTreePid() {
            return -1L;
        }
    }

}
